package org.aceor.mddal.gateway.executor.impl;

import org.aceor.mddal.common.sqlparser.result.context.MergeContext;
import org.aceor.mddal.common.executor.MergeUnit;
import org.aceor.mddal.gateway.merger.function.AggregateInvokeHandler;
import org.aceor.mddal.gateway.merger.groupby.GroupByInvokeHandler;
import org.aceor.mddal.gateway.resultset.AggregateResultSet;
import org.aceor.mddal.gateway.resultset.GroupByResultSet;
import org.aceor.mddal.gateway.resultset.IteratorResultSet;
import org.aceor.mddal.gateway.resultset.OrderByResultSet;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by lxue on 16/4/15.
 */
public class DefaultQueryMergeUnit implements MergeUnit<ResultSet, ResultSet> {

    private static final Logger log = LoggerFactory.getLogger(DefaultQueryMergeUnit.class);
    private MergeContext mergeContext;

    public DefaultQueryMergeUnit() {
    }

    public DefaultQueryMergeUnit(MergeContext mergeContext) {
        this.mergeContext = mergeContext;
    }

    @Override
    public ResultSet merge(List<ResultSet> params){
        ResultSet resultSet;
        try {
            switch (mergeContext.getResultSetType()) {
                case GroupBy:
                    resultSet = createDelegateResultSet(
                            new GroupByInvokeHandler(
                                    new GroupByResultSet(params, mergeContext)));
                    break;
                case Aggregate:
                    resultSet = createDelegateResultSet(
                            new AggregateInvokeHandler(
                                    new AggregateResultSet(params, mergeContext)));
                    break;
                case OrderBy:
                    resultSet = new OrderByResultSet(params, mergeContext);
                    break;
                case Iterator:
                    resultSet = new IteratorResultSet(params, mergeContext);
                    break;
                default:
                    throw new IllegalArgumentException("非法的ResultSetType :" + mergeContext.getResultSetType());
            }
            return resultSet;
        } catch (SQLException e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
        return null;
    }

    /**
     * 用于resultset get行记录值方法内部映射
     * @param handler
     * @return
     */
    private ResultSet createDelegateResultSet(final InvocationHandler handler) {
        return (ResultSet) Proxy.newProxyInstance(DefaultQueryMergeUnit.class.getClassLoader(), new Class[]{ResultSet.class}, handler);
    }
}
